package com.android.egoaccel;

import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import android.os.Environment;
import android.util.Log;

public class ValueStorage {
	private static BlockingQueue<String> AccelerationValues;
	private Thread WriteToDisk;
	private static FileWriter mFileWriter;
	private static boolean IAmBeingKilled = false;
	
	/**
	 * Constructor for Storage Component, initializes the various elements required 
	 * for storage.
	 * */
	public ValueStorage(){
		AccelerationValues = new LinkedBlockingQueue<String>();
		try {
			mFileWriter = new FileWriter(Environment.getExternalStorageDirectory()+"/Values.dat",true);
		} catch (IOException e) {
			e.printStackTrace();
		}
		WriteToDisk = new Thread(mRunnable);
		WriteToDisk.start();
		Log.i("CD/ValueStorage:", "Thread Started");
	}
	
	/**
	 * Stores the values for writing to disk.
	 * 
	 * @param timestamp timestamp of the acceleration value
	 * @param X X Axis acceleration Value
	 * @param Y Y Axis acceleration Value
	 * @param Z Z Axis acceleration Value
	 * 
	 * @return true when values have been stored in the temporary storage area for writing to disk.
	 * */
	public boolean PushNewTuple(long timestamp, float X, float Y, float Z){
		return AccelerationValues.offer(""+timestamp+" "+X+" "+Y+" "+Z);
	}
	
	/**
	 * When the thread is exiting, this is called to take care of the remaining values.
	 * */
	private boolean FinishWriting(){
		while(!AccelerationValues.isEmpty()){
			try {
				mFileWriter.write(""+AccelerationValues.poll()+"\n");
				mFileWriter.flush();
			} catch (IOException e) {
				Log.e("ValueStorage", "Trouble Writing values to disk in Finishing the Writing");
				e.printStackTrace();
			}
		}
		try {
			mFileWriter.close();
		} catch (IOException e) {
			Log.e("ValueStorage", "Trouble closing file after Writing");
			e.printStackTrace();
		}
		Log.i("CD/ValueStorage", "Done Cleaning up!");
		return true;
	}
	
	/**
	 * Thread object that writes values to disk
	 * */
	private Runnable mRunnable = new Runnable() {
		
		@Override
		public void run() {
			while(!IAmBeingKilled){
				try {
					mFileWriter.write(""+AccelerationValues.take()+"\n");
					mFileWriter.flush();
				} catch (IOException e) {
					Log.e("ValueStorage", "Trouble Writing values to disk in Thread");
					e.printStackTrace();
				} catch (InterruptedException e) {
					Log.e("ValueStorage", "Blocking Queue trouble in Thread");
					e.printStackTrace();
				}
			}
			Log.i("CD/ValueStorage", "Exiting Thread!");
			FinishWriting();
		}
	};
	
	/**
	 * Used to inform the thread to stop executing and start winding up the writing.
	 * 
	 * @param OnDestroyInvoked Flag to raise when onDestroy is called.
	 * */
	public void InformThread(boolean OnDestroyInvoked){ IAmBeingKilled = OnDestroyInvoked; }
	
}
